function string:split(sep, maxsplit)
	local fields, i, n = {}, 1, 0
	while true do
		local f, e = nil
		if not maxsplit or n < maxsplit then
			f, e = self:find(sep, i, true)
		end
		if f then
			table.insert(fields, self:sub(i, f - 1))
			i, n = e + 1, n + 1
		else
			table.insert(fields, self:sub(i))
			break
		end
	end
	return fields
end

function string:splitnumber(sep, maxsplit)
	local fields = self:split(sep, maxsplit)
	for i = 1, maxsplit and math.min(maxsplit, #fields) or #fields do
		fields[i] = tonumber(fields[i]) or 0
	end
	return fields
end

function table.slice(t, i, j)
	return table.move(t, i or 1, j or #t, 1, {})
end

function table.back(t)
	return t[#t]
end

function math.round(x)
	return math.floor(x + 0.5)
end

function math.lerp(v1, v2, t)
	return v1 + (v2 - v1) * t
end

function math.random_float(v1, v2)
	return math.lerp(v1, v2, math.random())
end

function IsMeanFalse(s)
	return not s or s == 0 or s == '0' or s == 'false' or s == ''
end

function IsMeanTrue(s)
	return not IsMeanFalse(s)
end

function NewIndexTable(t, key, arg)
	local value = t[key]
	if value ~= nil then return value end
	do value = arg or {}; t[key] = value; return value end
end

function FindInArray(t, arg, start, stop, step)
	for i = start or 1, stop or #t, step or 1 do
		if t[i] == arg then return i end
	end
end

function FindInTable(t, arg)
	for k, v in pairs(t) do
		if v == arg then return k end
	end
end

function RandomShuffle(t, e)
	local n = #t
	for i = 1, e and math.min(e, n - 1) or n - 1 do
		local j = math.random(i, n)
		if i ~= j then
			t[i], t[j] = t[j], t[i]
		end
	end
end

function Date2Time(s)
	local t = {}
	t.year, t.month, t.day, t.hour, t.min, t.sec =
		s:match('(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+)')
	return os.time(t)
end

function Class(t)
	local cls = t or {}
	cls.__index = cls
	function cls:new(t)
		local obj = t or {}
		setmetatable(obj, self)
		return obj
	end
	return cls
end